# -*- coding: utf-8 -*-
from numpy import *
from os import listdir
import classify


'''
本例将实现一个手写输入识别系统
'''

'''
该方法用于将样本数字图片转换为一个1*1024的矩阵向量

目标：
通过分析样本数据,利用算法对测试数据中的数字进行识别.

思路分析：
从条件来看 该问题属于监督学习中的分类问题（有样本数据且样本数据有明确的结果，结果是离散的）
1.对文件中的样本数据进行预处理，转化成程序可以接受的格式 
 本例中，给出的训练样本是一组32*32的由0和1组成的数字矩阵,需要识别的数字在矩阵中由数字1来组成手写的数字形状
 我们可以将该数字矩阵转化成一个1*1024（32*32=1024）的特征向量,问题即转化为一个有1024个特征值和1个目标结果的分类问题
2.对特征数据进行归一化处理,本例中因为数字只有0和1 所以不需要进行归一化处理
4.利用编写好的classify0分类器 对样本数据进行分类
5.测试验证， 本例中样本训练数据和测试数据是分开的，

优点：
1.简单 易于实现
2.识别效果相对较好

缺点：
1.当训练样本数据很大的时候，需要计算每个测试样本和训练样本直接的距离，计算量很大，很耗时,占用存储空间

'''

'''
该方法用于将样本文件中的数字矩阵，转化为一个1*1024的特征向量
'''
def image2vector(file_name):
    return_vector=zeros([1,1024])
    fr=open(file_name)
    for i in range(32):
        line_str=fr.readline()  #从文件中读取一行
        for j in range(32):
            return_vector[0,32*i+j]=int(line_str[j])  #将字符串中的字符一个一个赋值到return_vetcor矩阵的每一列中

    return return_vector


'''
该方法用于从样本文件夹中获取所有的样本数据,并转化成分类器需要的格式
'''
def get_mat(file_path):
    target_num_labels=[]
    train_list=listdir(file_path)
    train_sample_count=len(train_list)
    train_mat=zeros((train_sample_count,1024))

    for i in range(train_sample_count):
        file_name=train_list[i] #文件名的格式如  0_1.txt
        pre_file_name=file_name.split(".")[0]  #文件名前缀
        temp_str_list=pre_file_name.split("_")
        class_num=int(temp_str_list[0]) # 取出该文件对应的数字
        target_num_labels.append(class_num) #将该数字作为标签存储
        train_mat[i,:]=image2vector(file_path+"/"+file_name)

    return train_mat,target_num_labels


if __name__ == '__main__':
    train_mat, train_labels=get_mat('/Users/ting/Documents/个人资料/文档资料/机器学习/机器学习实战代码/Ch02/digits/trainingDigits')
    test_mat, test_labels=get_mat('/Users/ting/Documents/个人资料/文档资料/机器学习/机器学习实战代码/Ch02/digits/testDigits')
    test_count=len(test_mat)
    error_count=0
    for i in range(test_count):
        classify_result=classify.classify0(test_mat[i,:],train_mat,train_labels,4)
        print("验证分类结果为 d%,实际分类为: d%", classify_result, test_labels[i])
        if classify_result != test_labels[i]:
            error_count += 1

    print("总的测试错误个数为:", error_count)



